#ifndef __M_LOOP_H__
#define __M_LOOP_H__
#include "util.hpp"
#include "buffer.hpp"
#include <vector>
#include <thread>
#include <mutex>
#include <atomic>
#include <condition_variable>
#include <functional>

namespace Log{
    const char LOG_SEPARATOR = 0x1F;//定义分隔符号
    class AsyncLooper {
        public:
            using Functor = std::function<void(Buffer &buffer)>;
            using ptr = std::shared_ptr<AsyncLooper>;
            AsyncLooper(const Functor &cb): _running(true), _looper_callback(cb),
                _thread(std::thread(&AsyncLooper::worker_loop,this)) //thread执行的函数和传递的参数是类本身(传成员函数作为执行函数的时候，要传递this指针作为上下文的绑定)
                {
            }
            ~AsyncLooper() { stop(); }
            void stop(){ 
                _running = false; 
                _pop_cond.notify_all();
                _thread.join();
            }

            
            void push(const std::string &msg){
                if (_running == false) return;
                {
                    std::unique_lock<std::mutex> lock(_mutex);
                    _push_cond.wait(lock, [&]{ return _tasks_push.writeAbleSize() >= msg.size(); });//wait函数的重载版本，可以附带一个谓词，只有谓词返回true才会使得wait函数返回（此时线程被唤醒）
                    _tasks_push.push(msg.c_str(), msg.size());
                }
                _pop_cond.notify_all();
            }
            
            
        private:
            void worker_loop(){
                while(1){
                    {
                        std::unique_lock<std::mutex> lock(_mutex);
                        if (_running == false && _tasks_push.empty()) { return; }
                        _pop_cond.wait(lock, [&]{ return !_tasks_push.empty() || !_running; });
                        _tasks_push.swap(_tasks_pop);
                    }//使用{}划定区间，出该区间lock被释放，也就是为互斥锁设置一个生命周期（并不对数据的处理加锁）
                    _push_cond.notify_all();
                    _looper_callback(_tasks_pop);
                    _tasks_pop.reset();//处理完数据后重置pop缓冲区
                }
                return;
            }
        private:
            Functor _looper_callback;
        
        private:
            std::mutex _mutex;
            std::atomic<bool> _running;
            std::condition_variable _push_cond;
            std::condition_variable _pop_cond;
            Buffer _tasks_push;
            Buffer _tasks_pop;
            std::thread _thread;
            
    };
}





#endif